package server1

import (
	"fmt"
	"log"
	"net"
	"strconv"
	"time"
	"zinxtcp/route"
	"zinxtcp/tunny"
	"zinxtcp/utils"
	"zinxtcp/ziface"
)

//iServer 接口实现，定义一个Server服务类
type Server1 struct {
	//服务器的名称
	Name string
	//tcp4 or other
	IPVersion string
	//服务绑定的IP地址
	IP string
	//服务绑定的端口
	Port int
	//监听器
	listener *net.TCPListener
	//当前Server的链接管理器
	ConnMgr ziface.IConnManager
}

//============== 实现 ziface.IServer 里的全部接口方法 ========

//开启网络服务
func (s *Server1) Start() {
	fmt.Printf("[START] Server listenner at IP: %s, Port %d, is starting\n", s.IP, s.Port)
	fmt.Printf("[Zinx] Version: %s, MaxConn: %d,  MaxPacketSize: %d\n",
		utils.GlobalObject.Version,
		utils.GlobalObject.MaxConn,
		utils.GlobalObject.MaxPacketSize)

	s.ConnMgr.Listening(s.listener)
}

func (s *Server1) Stop() {
	fmt.Println(s.ConnMgr.Len())
	fmt.Println("[STOP] Zinx server , name ", s.Name)

	//关闭新的连接，关闭所有连接的读取
	//_ = s.listener.Close()

	go func() {
		s.ConnMgr.Stop()
		//将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
		//s.ConnMgr.ClearConn()
		tunny.LabourPool.Close()
	}()
	<-time.After(time.Duration(1) * time.Second)
	fmt.Println("[STOP] Zinx server complete ")
}

func (s *Server1) Serve() error {
	listener, err := s.listenerInit()
	if err != nil {
		log.Fatalf("server start failed with error:　％v", err)
		return err
	}
	s.listener = listener
	go s.Start()

	//TODO Server.Serve() 是否在启动服务的时候 还要处理其他的事情呢 可以在这里添加
	return nil
}

func (s *Server1) listenerInit() (*net.TCPListener, error) {
	tcpAddr, err := net.ResolveTCPAddr(s.IPVersion, s.IP+":"+strconv.Itoa(s.Port))
	if err != nil {
		panic("解析ip地址失败: " + err.Error())
	}
	log.Printf("Listening %s:%d ....\n", s.IP, s.Port)
	listener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		panic("监听TCP失败: " + err.Error())
	}
	log.Printf("Listen success on %s:%d with tcp4\n", s.IP, s.Port)
	return listener, nil
}

func (s *Server1) AddRouter(msgId uint32, router ziface.IHandler) {
	route.Route.AddRouter(msgId, router)
}

func (s *Server1) SetEncoder(encoder ziface.IEncoder) {
	s.ConnMgr.SetEncoder(encoder)
}

func (s *Server1) SetConnEvent(connEvent ziface.IConnEvent) {
	s.ConnMgr.SetConnEvent(connEvent)
}

/*
  创建一个服务器句柄
*/
func NewServer1(ConfFilePath string) ziface.IServer {
	//先初始化全局配置文件
	utils.GlobalObject.Reload(ConfFilePath)

	s := &Server1{
		Name:      utils.GlobalObject.Name, //从全局参数获取
		IPVersion: "tcp4",
		IP:        utils.GlobalObject.Host,    //从全局参数获取
		Port:      utils.GlobalObject.TcpPort, //从全局参数获取
		ConnMgr:   NewConnManager(),           //创建ConnManager
	}

	return s
}
